#pragma once
#include <iostream>
#include <vector>
#include <atomic>
#include <mutex>
template <typename T>
class RingQueue
{
	static_assert(std::is_move_constructible<T>::value,
				  "Should be of movable type");

public:
	RingQueue(size_t size)
		: _queue(size), _en_queue(0), _de_queue(0)
	{
		bool size_is_power_of_2 = (size >= 2) && ((size & (size - 1)) == 0);
		if (!size_is_power_of_2)
		{
			throw std::invalid_argument("buffer size should be a power of 2");
		}
		mask = size - 1;
	}

	RingQueue(RingQueue &&q) noexcept
	{
		*this = std::move(q);
	}
	RingQueue &operator=(RingQueue &&q) noexcept
	{
		if (this != &q)
		{
			_queue = std::move(q._queue);
			mask = std::move(q.mask);
			_en_queue = q._en_queue.load();
			_de_queue = q._de_queue.load();
		}
		return *this;
	}

	template <typename U>
	bool push(U &&val)
	{

		size_t pos;
		while (true)
		{
			pos = _en_queue.load(std::memory_order_relaxed);

			if (((pos + 1) & mask) == _de_queue.load(std::memory_order_relaxed))
			{
				// std::cout << "线程" << "任务失败" << std::endl;
				return false;
			}

			if (_en_queue.compare_exchange_weak(pos, (pos + 1) & (mask), std::memory_order_relaxed))
			{
				break;
			}
		}

		// std::cout << "线程" << "任务" << std::endl;
		_queue[pos] = std::forward<U>(val);
		return true;
	}

	bool pop(T &data)
	{
		size_t pos;
		// std::cout << "线程" << "弹出任务" << std::endl;
		while (true)
		{
			pos = _de_queue.load(std::memory_order_relaxed);

			if (pos == _en_queue.load(std::memory_order_relaxed))
			{
				// std::cout << "线程" << "弹出任务失败" << std::endl;
				return false;
			}

			if (_de_queue.compare_exchange_weak(pos, (pos + 1) & (mask), std::memory_order_relaxed))
			{
				break;
			}
		}

		data = std::move(_queue[pos]);
		return true;
	}

	~RingQueue()
	{
	}

private:
	RingQueue(RingQueue &) = delete;
	RingQueue &operator=(RingQueue &) = delete;

	typedef char cacheline[64];

	size_t mask;
	cacheline pad1;
	std::vector<T> _queue;
	cacheline pad2;
	std::atomic<size_t> _en_queue;
	cacheline pad3;
	std::atomic<size_t> _de_queue;
};
